<?php

namespace App\Containers\AppSection\Project\Models;

use App\Containers\AppSection\BankDetail\Models\BankDetail;
use App\Containers\AppSection\File\Models\File;
use App\Containers\AppSection\Moderation\Models\Moderation;
use App\Containers\AppSection\Pledge\Models\Pledge;
use App\Containers\AppSection\Profile\Models\Profile;
use App\Containers\AppSection\Status\Models\Status;
use App\Containers\AppSection\Type\Models\Type;
use App\Ship\Parents\Models\Model;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
use Staudenmeir\EloquentJsonRelations\Relations\BelongsToJson;

/**
 * Проект
 *
 * @property int $id Id
 * @property int $profile_id Профиль
 * @property string $title Наименование
 * @property string $description Описание
 * @property bool $is_draft Черновик
 * @property string $stage_key Стадия
 * @property array $videos Видео
 * @property string $moderation_status_key Статус модерации
 * @property string $project_rating_key Рейтинг проекта
 * @property string $profile_rating_key Рейтинг профиля
 * @property string $document_rating_key Рейтинг документов
 * @property int $company_id Компания
 * @property int $condition_id Цель
 * @property array $businesses Бизнес модели
 * @property array $rate Тариф
 * @property int $moderation_id  Модерация
 * @property int $analytic_id Аналитика
 * @property int $government_id Сведения о структуре органов управления
 * @property Carbon $moderated_at Время Модерации
 * @property Carbon $created_at Время создания
 * @property Carbon $updated_at Время обновления
 *
 * @property Profile $profile Профиль
 * @property Status $moderation_status Статус модерации
 * @property Company $company Компания
 * @property Condition $condition Цель
 * @property Type $stage Стадия
 * @property Type $project_rating Рейтинг проекта
 * @property Type $profile_rating Рейтинг профиля
 * @property Type $document_rating Рейтинг документов
 * @property Type $rating Рейтинг
 * @property Document[] $documents Документы
 * @property File[] $medias Медиа
 * @property Pledge[] $pledges Залоги
 * @property BankDetail $bank_detail Банковские реквизиты
 * @property Moderation $moderation Модерация
 * @property Moderation $moderations Модерации
 * @property Analytic $analytic Аналитика
 * @property Government $government Сведения о структуре органов управления
 */
class Project extends Model
{
    use HasJsonRelationships;

    protected $fillable = [
        'profile_id',
        'title',
        'description',
        'is_draft',
        'stage_key',
        'moderation_status_key',
        'project_rating_key',
        'profile_rating_key',
        'document_rating_key',
        'company_id',
        'condition_id',
        'businesses',
        'rate',
        'moderation_id',
        'medias',
        'videos',
        'analytic_id',
        'government_id',
        'moderated_at',
    ];

    protected $casts = [
        'businesses' => 'json',
        'rate' => 'json',
        'medias' => 'json',
        'videos' => 'json',
    ];

    protected $dates = [
        'created_at',
        'updated_at',
        'moderated_at'
    ];

    /**
     * A resource key to be used in the serialized responses.
     */
    protected string $resourceKey = 'Project';

    /**
     * Профиль
     * @return BelongsTo|Profile Profile
     */
    public function profile(): BelongsTo
    {
        return $this->belongsTo(Profile::class, 'profile_id', 'id');
    }

    /**
     * Стадия
     * @return BelongsTo Type
     */
    public function stage(): BelongsTo
    {
        return $this->belongsTo(Type::class, 'stage_key', 'key');
    }

    /**
     * Статус модерации
     * @return BelongsTo Status
     */
    public function moderation_status(): BelongsTo
    {
        return $this->belongsTo(Status::class, 'moderation_status_key', 'key');
    }

    /**
     * Компания
     * @return BelongsTo Company
     */
    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class, 'company_id', 'id');
    }

    /**
     * Цель
     * @return BelongsTo Condition
     */
    public function condition(): BelongsTo
    {
        return $this->belongsTo(Condition::class, 'condition_id', 'id');
    }

    /**
     * Документы
     * @return HasMany|Document Documents
     */
    public function documents(): HasMany
    {
        return $this->hasMany(Document::class, 'project_id', 'id');
    }

    /**
     * Медиа
     * @return BelongsToJson Files
     */
    public function medias(): belongsToJson
    {
        return $this->belongsToJson(File::class, 'medias');
    }

    /**
     * Банковские реквизиты
     * @return BelongsTo BankDetail
     */
    public function bank_detail(): BelongsTo
    {
        return $this->belongsTo(BankDetail::class)->withDefault(function () {
            return new BankDetail();
        });
    }

    /**
     * Рейтинг
     * @return BelongsTo Type
     */
    public function project_rating(): BelongsTo
    {
        return $this->belongsTo(Type::class, 'project_rating_key', 'key');
    }

    /**
     * Рейтинг профиля
     * @return BelongsTo Type
     */
    public function profile_rating(): BelongsTo
    {
        return $this->belongsTo(Type::class, 'profile_rating_key', 'key');
    }

    /**
     * Рейтинг документов
     * @return BelongsTo Type
     */
    public function document_rating(): BelongsTo
    {
        return $this->belongsTo(Type::class, 'document_rating_key', 'key');
    }

    /**
     * Рейтинг документов
     * @return BelongsTo Type
     */
    public function rating(): BelongsTo
    {
        $ratings = ['a+' => 5, 'a' => 4, 'b' => 3, 'c' => 2, 'd' => 1];
        $pledgeRatings = $this->pledges()->pluck('rating_key')->toArray();

        $sum = $ratings[$this->project_rating_key] + $ratings[$this->profile_rating_key] + $ratings[$this->document_rating_key];
        $sum += $ratings[$this->condition->rating_key];

        foreach ($pledgeRatings as $pledgeRating) {
            $sum += $ratings[$pledgeRating];
        }
        $count = 4 + count($pledgeRatings);

        return $this->belongsTo(Type::class)->withDefault(
            Type::where('key', array_flip($ratings)[round($sum / $count)])->first()->toArray()
        );
    }

    /**
     * Залоги
     * @return HasMany Pledge
     */
    public function pledges(): HasMany
    {
        return $this->hasMany(Pledge::class, 'project_id', 'id');
    }

    /**
     * Модерация
     * @return BelongsTo Moderation
     */
    public function moderation(): BelongsTo
    {
        return $this->belongsTo(Moderation::class, 'moderation_id', 'id');
    }

    /**
     * Модерации
     * @return HasMany Moderations
     */
    public function moderations(): HasMany
    {
        return $this->hasMany(Moderation::class, 'project_id', 'id');
    }

    /**
     * Аналитика
     * @return BelongsTo Analytic
     */
    public function analytic(): BelongsTo
    {
        return $this->belongsTo(Analytic::class, 'analytic_id', 'id');
    }

    /**
     * Сведения о структуре органов управления
     * @return BelongsTo Government
     */
    public function government(): BelongsTo
    {
        return $this->belongsTo(Government::class, 'government_id', 'id');
    }


    /**
     * @param $status
     * @return bool
     */
    public function hasModerationStatus(...$status): bool
    {
        return in_array($this->moderation_status_key, $status);
    }
}
